/*
 * Created on Mar 29, 2006
 *
 */
package org.reprap;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JSplitPane;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;

import org.reprap.geometry.Producer;
import org.reprap.machines.MachineFactory;
import org.reprap.gui.RepRapBuild;
import org.reprap.gui.Utility;
import org.reprap.gui.botConsole.BotConsoleFrame;
import org.reprap.comms.Communicator;
import org.reprap.utilities.ExtensionFileFilter;
import org.reprap.utilities.RrDeleteOnExit;
import org.reprap.utilities.Debug;

/**
 *
 * mainpage RepRap Host Controller Software
 * 
 * section overview Overview
 * 
 * Please see http://reprap.org/ for more details.
 *  
 */


public class Main {
	
	public static RrDeleteOnExit ftd = null;

    private static Communicator communicator = null;
    
    private static boolean repRapAttached = false;
    
    private Producer producer = null;
    
    private Printer printer = null;
    
    // Window to walk the file tree
    
    private JFileChooser chooser;
    private JFrame mainFrame;
    private RepRapBuild builder;
//    private PreviewPanel preview = null;
//    private JCheckBoxMenuItem viewBuilder;
//    private JCheckBoxMenuItem viewPreview;
    private JCheckBoxMenuItem segmentPause;
    private JCheckBoxMenuItem layerPause;
    
    private JMenuItem cancelMenuItem;
    private JMenuItem produceProduceB;

    public void setSegmentPause(boolean state) {
        segmentPause.setState(state);
    }
    
    public void setLayerPause(boolean state) {
        layerPause.setState(state);
    }
    
    public void clickCancel() {
        cancelMenuItem.doClick();
    }
    
    private JSplitPane panel;
	
	public Main() {
		ftd = new RrDeleteOnExit();
        chooser = new JFileChooser();
 
        // Do we want just to list .stl files, or all?
        // If all, comment out the next two lines
        
        FileFilter filter = new ExtensionFileFilter("STL", new String[] { "STL" });
        chooser.setFileFilter(filter);
        try
        {
        	printer = MachineFactory.create();
        } catch (Exception ex)
        {
        	System.err.println("MachineFactory.create() failed.\n" +
        			ex.toString());
        }
	}

	private void createAndShowGUI() throws Exception {
        JFrame.setDefaultLookAndFeelDecorated(false);
        mainFrame = new JFrame("RepRap             grid: 20 mm");
        mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        // Required so menus float over Java3D
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
        
        // Create menus
        JMenuBar menubar = new JMenuBar();
        
        //JMenu fileMenu = new JMenu("File");
        //fileMenu.setMnemonic(KeyEvent.VK_F);
        //menubar.add(fileMenu);
        
        //JMenuItem fileOpen = new JMenuItem("Open...", KeyEvent.VK_O);
        //fileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
        //fileOpen.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		onOpen();
		//	}});
        //fileMenu.add(fileOpen);
        
        //fileMenu.addSeparator();

        //JMenuItem filePrefs = new JMenuItem("Preferences...", KeyEvent.VK_R);
        //filePrefs.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		Preferences prefs = new Preferences();
		//		prefs.setVisible(true);	// prefs.show();
		//	}});
        //fileMenu.add(filePrefs);

        //fileMenu.addSeparator();

        //JMenuItem fileExit = new JMenuItem("Exit", KeyEvent.VK_X);
        //fileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK));
        //fileExit.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		dispose();
		//	}});
        //fileMenu.add(fileExit);

        JMenu viewMenu = new JMenu("View");
        viewMenu.setMnemonic(KeyEvent.VK_V);
        menubar.add(viewMenu);

//        JMenuItem viewToggle = new JMenuItem("Toggle view", KeyEvent.VK_V);
//        viewToggle.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK));
//        viewToggle.addActionListener(new ActionListener() {
//			public void actionPerformed(ActionEvent arg0) {
//				onViewToggle();
//			}});
//        viewMenu.add(viewToggle);
        
//        viewBuilder = new JCheckBoxMenuItem("Setup build");
//        viewBuilder.setSelected(true);
//        viewBuilder.addActionListener(new ActionListener() {
//			public void actionPerformed(ActionEvent arg0) {
//				onViewBuilder();
//			}});
//        viewMenu.add(viewBuilder);
        
//        viewPreview = new JCheckBoxMenuItem("Progress");
//        viewPreview.addActionListener(new ActionListener() {
//			public void actionPerformed(ActionEvent arg0) {
//				onViewPreview();
//			}});
//        viewMenu.add(viewPreview);

        
        JMenu manipMenu = new JMenu("Manipulate");
        manipMenu.setMnemonic(KeyEvent.VK_M);
        menubar.add(manipMenu);

        JMenuItem manipX = new JMenuItem("Rotate X", KeyEvent.VK_X);
        manipX.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK));
        manipX.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				onRotateX();
			}});
        manipMenu.add(manipX);

        JMenuItem manipY = new JMenuItem("Rotate Y", KeyEvent.VK_Y);
        manipY.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.CTRL_MASK));
        manipY.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				onRotateY();
			}});
        manipMenu.add(manipY);

        JMenuItem manipZ = new JMenuItem("Rotate Z", KeyEvent.VK_Z);
        manipZ.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
        manipZ.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				onRotateZ();
			}});
        manipMenu.add(manipZ);
        
        JMenuItem inToMM = new JMenuItem("Scale by 25.4 (in -> mm)", KeyEvent.VK_I);
        inToMM.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, ActionEvent.CTRL_MASK));
        inToMM.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				oninToMM();
			}});
        manipMenu.add(inToMM);
        
        JMenuItem nextP = new JMenuItem("Select next object that will be built", KeyEvent.VK_N);
        nextP.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
        nextP.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				onNextPicked();
			}});
        manipMenu.add(nextP);
        
        JMenuItem reorder = new JMenuItem("Reorder the building sequence", KeyEvent.VK_R);
        reorder.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.CTRL_MASK));
        reorder.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				onReorder();
			}});
        manipMenu.add(reorder);
        
        
        JMenuItem deleteSTLW = new JMenuItem("Delete selected object", KeyEvent.VK_W);
        deleteSTLW.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, ActionEvent.CTRL_MASK));
        deleteSTLW.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				onDelete();
			}});
        manipMenu.add(deleteSTLW);
        
        JMenuItem deleteSTL = new JMenuItem("Delete selected object", KeyEvent.VK_DELETE);
        deleteSTL.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
        deleteSTL.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				onDelete();
			}});
        manipMenu.add(deleteSTL);
        
        

        //JMenu produceMenu = new JMenu("Build");
        //produceMenu.setMnemonic(KeyEvent.VK_P);
        //menubar.add(produceMenu);

        
        produceProduceB = new JMenuItem("Start build...", KeyEvent.VK_B);
        produceProduceB.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, ActionEvent.CTRL_MASK));
        produceProduceB.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				onProduceB();
			}});
        //produceMenu.add(produceProduceB);

        cancelMenuItem = new JMenuItem("Cancel", KeyEvent.VK_P);
        cancelMenuItem.setEnabled(false);
        cancelMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(producer != null)
					producer.setCancelled(true);
			}});
        //produceMenu.add(cancelMenuItem);
        
        
        
        //produceMenu.addSeparator();

        segmentPause = new JCheckBoxMenuItem("Pause before segment");
        //produceMenu.add(segmentPause);

        layerPause = new JCheckBoxMenuItem("Pause before layer");
        //produceMenu.add(layerPause);

        //produceMenu.addSeparator();
        
        //JMenuItem estimateMenuItemB = new JMenuItem("Estimate build resources...", KeyEvent.VK_E);
        //estimateMenuItemB.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		estimateResourcesB();
		//	}});
        //produceMenu.add(estimateMenuItemB);
                
        //JMenu toolsMenu = new JMenu("Tools");
        //toolsMenu.setMnemonic(KeyEvent.VK_T);
        //menubar.add(toolsMenu);
        
        //JMenuItem toolsWorkingVolume = new JMenuItem("Working volume probe", KeyEvent.VK_W);
        //toolsWorkingVolume.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		try {
		//			new org.reprap.gui.steppertest.WorkingVolumeFrame();
		//		}
        //     	catch (Exception ex) {
        //     		JOptionPane.showMessageDialog(null, "Working volume probe exception: " + ex);
        // 			ex.printStackTrace();
        //     	}
		//	}});
        //toolsMenu.add(toolsWorkingVolume);
        
      //JMenuItem toolsMaintenancePositions = new JMenuItem("Maintenance positions", KeyEvent.VK_M);
      //toolsMaintenancePositions.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		try {
		//			new org.reprap.gui.steppertest.MaintenancePositionsFrame();
		//		}
        //    	catch (Exception ex) {
        //   		JOptionPane.showMessageDialog(null, "Maintenance positions exception: " + ex);
       	//		ex.printStackTrace();
        //   	}
		//	}});
      //toolsMenu.add(toolsMaintenancePositions);
        
        //JMenuItem toolsExerciser = new JMenuItem("Stepper exerciser", KeyEvent.VK_S);
        //toolsExerciser.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		try {
		//			org.reprap.gui.steppertest.Main.main(null);
		//		}
        //      	catch (Exception ex) {
        //    		JOptionPane.showMessageDialog(null, "Stepper exerciser exception: " + ex);
        // 			ex.printStackTrace();
        //     	}
		//	}});
        //toolsMenu.add(toolsExerciser);

        //JMenuItem toolsExtruderExerciser = new JMenuItem("Extruder exerciser", KeyEvent.VK_E);
        //toolsExtruderExerciser.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		try {
		//			org.reprap.gui.extrudertest.Main.main(null);
		//		}
        //      	catch (Exception ex) {
        //     		JOptionPane.showMessageDialog(null, "Extruder exerciser exception: " + ex);
        // 			ex.printStackTrace();
        //     	}
		//	}});
        //toolsMenu.add(toolsExtruderExerciser);

        //JMenuItem toolsExtruderProfiler = new JMenuItem("Extruder heat profiler", KeyEvent.VK_H);
        //toolsExtruderProfiler.addActionListener(new ActionListener() {
		//	public void actionPerformed(ActionEvent arg0) {
		//		try {
		//			org.reprap.gui.extruderprofile.Main.main(null);
		//		}
        //      	catch (Exception ex) {
        //     		JOptionPane.showMessageDialog(null, "Extruder profiler exception: " + ex);
        // 			ex.printStackTrace();
        //     	}
		//	}});
        //toolsMenu.add(toolsExtruderProfiler);

        

        //JMenu diagnosticsMenu = new JMenu("Diagnostics");
        //toolsMenu.add(diagnosticsMenu);
        //JMenuItem diagnosticsCommsTest = new JMenuItem("Basic comms test");
        //diagnosticsMenu.add(diagnosticsCommsTest);

        // Create the main window area
        // This is a horizontal box layout that includes
        // both the builder and preview screens, one of
        // which may be invisible.

        Box builderFrame = new Box(BoxLayout.Y_AXIS);
        builderFrame.add(new JLabel("Setup build"));
        builder = new RepRapBuild();
        builderFrame.setMinimumSize(new Dimension(0,0));
        builderFrame.add(builder);
        
        panel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); 
        panel.setPreferredSize(Utility.getDefaultAppSize());
        panel.setMinimumSize(new Dimension(0, 0));
        panel.setResizeWeight(0.5);
        panel.setOneTouchExpandable(true);
        panel.setContinuousLayout(true);
        panel.setLeftComponent(builderFrame);
//        if(org.reprap.Preferences.loadGlobalBool("DisplaySimulation"))
//        	panel.setRightComponent(createPreviewPanel());
//        else
//        	preview = null;
        panel.setDividerLocation(panel.getPreferredSize().width);
        
        mainFrame.getContentPane().add(panel);
                
        mainFrame.setJMenuBar(menubar);
        
        mainFrame.pack();
        Utility.positionWindowOnScreen(mainFrame);
        mainFrame.setVisible(true);
	}
	
	protected void finalize() throws Throwable
	{
		Debug.d("Main finalise()");
		ftd.killThem();
	}

//	private Box createPreviewPanel() throws Exception {
//		
//        Box pane = new Box(BoxLayout.Y_AXIS);
//        pane.add(new JLabel("Build progress"));
//		preview = new PreviewPanel();
//		pane.setMinimumSize(new Dimension(0,0));
//		if(preview != null)
//			pane.add(preview);
//		
//		return pane;
//	}
	
//	private void onProduceT() {
//        cancelMenuItem.setEnabled(true);
//        produceProduceT.setEnabled(false);
//		Thread t = new Thread() {
//			public void run() {
//				Thread.currentThread().setName("Producer");
//				try {
//					// TODO Some kind of progress indicator would be good
//					
//					if (!viewPreview.isSelected()) {
//						viewPreview.setSelected(true);
//						updateView();
//					}
//
////					if(preview != null)
////					{
////						preview.setSegmentPause(segmentPause);
////						preview.setLayerPause(layerPause);
////					}
//					
//					producer = new Producer(printer, preview, builder);
//					producer.setSegmentPause(segmentPause);
//					producer.setLayerPause(layerPause);
//					producer.produce();
//					String usage = getResourceMessage(producer);
//					producer.dispose();
//					producer = null;
//			        cancelMenuItem.setEnabled(false);
//			        produceProduceT.setEnabled(true);
//					JOptionPane.showMessageDialog(mainFrame, "Production complete.  " +
//							usage);
//				}
//				catch (Exception ex) {
//					JOptionPane.showMessageDialog(mainFrame, "Production exception: " + ex);
//					ex.printStackTrace();
//				}
//			}
//		};
//		t.start();
//	}
	
	/**
	 * Return the printer being used
	 */
	public Printer getPrinter()
	{
		return printer;
	}
	
	/**
	 * Stop production
	 *
	 */
	public void pause()
	{
		if(producer != null)
			producer.pause();
		try
		{
			printer.stopMotor();
			printer.stopValve();
			printer.pause();
		} catch (Exception ex) {}
	}
	
	/**
	 * Resume production
	 * NB: does not re-start the extruder
	 *
	 */
	public void resume()
	{
		printer.resume();
		if(producer != null)
			producer.resume();
	}
	
	public int getLayers()
	{
		if(producer == null)
			return 0;
		return producer.getLayers();
	}
	
	public int getLayer()
	{
		if(producer == null)
			return 0;
		return producer.getLayer();
	}
	
	public void onProduceB() {
        cancelMenuItem.setEnabled(true);
        produceProduceB.setEnabled(false);
		Thread t = new Thread() {
			public void run() {
				Thread.currentThread().setName("Producer");
				try {
					
//					if (!viewPreview.isSelected()) {
//						viewPreview.setSelected(true);
//						updateView();
//					}
					
//					if(preview != null)
//					{
//						preview.setSegmentPause(segmentPause);
//						preview.setLayerPause(layerPause);
//					}
					
					if(printer == null)
						System.err.println("Production attempted with null printer.");
					producer = new Producer(printer, builder);
					producer.setSegmentPause(segmentPause);
					producer.setLayerPause(layerPause);
					producer.produce();
					String usage = getResourceMessage(producer);
					producer.dispose();
					producer = null;
			        cancelMenuItem.setEnabled(false);
			        produceProduceB.setEnabled(true);
					JOptionPane.showMessageDialog(mainFrame, "Production complete.");// +	usage);
				}
				catch (Exception ex) {
					JOptionPane.showMessageDialog(mainFrame, "Production exception: " + ex);
					ex.printStackTrace();
				}
			}
		};
		t.start();
	}
	
    public String onOpen(boolean rfo) 
    {
        String result = null;
        File f;
        FileFilter filter;
        
        if(rfo)
        	filter = new ExtensionFileFilter("RFO", new String[] { "RFO" });
        else
        	filter = new ExtensionFileFilter("STL", new String[] { "STL" });
        chooser.setFileFilter(filter);

        int returnVal = chooser.showOpenDialog(null);// chooser.showOpenDialog(mainFrame);
        if(returnVal == JFileChooser.APPROVE_OPTION) 
        {
            f = chooser.getSelectedFile();
            result = "file:" + f.getAbsolutePath();
            if(rfo)
            	builder.addRFOFile(result);
            else
            	builder.anotherSTLFile(result);

            return f.getName();
        }
        return "";
    }
    
    public String saveRFO(String fileRoot)
    {
        String result = null;
        File f;
        FileFilter filter;
        
        
		File defaultFile = new File(fileRoot + ".rfo");
		JFileChooser chooser = new JFileChooser();
		chooser.setSelectedFile(defaultFile);
		filter = new ExtensionFileFilter("RFO file to write to", new String[] { "rfo" });
		chooser.setFileFilter(filter);
		chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
 
        chooser.setFileFilter(filter);

        int returnVal = chooser.showSaveDialog(null);// chooser.showOpenDialog(mainFrame);
        if(returnVal == JFileChooser.APPROVE_OPTION) 
        {
            f = chooser.getSelectedFile();
            result = "file:" + f.getAbsolutePath();

            	builder.saveRFOFile(result);
            return f.getName();
        }
        return "";   	
    }
    
    public void deleteAllSTLs()
    {
    	builder.deleteAllSTLs();
    }
    
    private void onRotateX() {
    	  builder.xRotate();
    }

    private void onRotateY() {
  	  builder.yRotate();
    }

    private void onRotateZ() {
  	  builder.zRotate();
    }
    
    private void oninToMM() {
    	  builder.inToMM();
      } 
    
    private void onNextPicked()
    {
    	builder.nextPicked();
    }
    
    private void onReorder()
    {
    	builder.doReorder();
    }
    
//    private void onMaterial() {
//  	  builder.materialSTL();
//    }
    
    private void onDelete() {
    	  builder.deleteSTL();
      }
    
    public void mouseToWorld()
    {
    	builder.mouseToWorld();
    }

//	private void onViewBuilder() {
////    		if (!viewBuilder.isSelected() && !viewPreview.isSelected())
////    			viewPreview.setSelected(true);
//        	updateView();
//    }

//    private void onViewPreview() {
//		if (!viewPreview.isSelected() && !viewBuilder.isSelected())
//			viewBuilder.setSelected(true);
//		updateView();
//    }
    
//    private void onViewToggle() {
//    		if (viewBuilder.isSelected()) {
//    			viewPreview.setSelected(true);
//    			viewBuilder.setSelected(false);
//    		} else {
//    			viewPreview.setSelected(false);
//    			viewBuilder.setSelected(true);
//    		}
//        	updateView();
//    }
    
//    private void updateView() {
////    	    if (viewBuilder.isSelected() && viewPreview.isSelected())
////    	    	  panel.setDividerLocation(0.5);
////    	    else if (viewBuilder.isSelected())
//  	    	  panel.setDividerLocation(1.0);
////    	    else
////    	    	  panel.setDividerLocation(0.0);
//    }
    
//    private void estimateResourcesT() {
//	    	EstimationProducer eProducer = null;
//	    	try {
//	    		eProducer = new EstimationProducer(builder);
//	    		eProducer.produce();
//	    		JOptionPane.showMessageDialog(mainFrame,
//	    				"Expected " + getResourceMessage(eProducer));
//	    		
//	    	} catch (Exception ex) {
//	    		JOptionPane.showMessageDialog(null, "Exception during estimation: " + ex);    
//	    	} finally {
//	    		if (eProducer != null)
//	    			eProducer.dispose();
//	    	}
//    }
    
//    private void estimateResourcesB() {
//    	EstimationProducer eProducer = null;
//    	try {
//    		eProducer = new EstimationProducer(builder);
//    		eProducer.produce();
//    		JOptionPane.showMessageDialog(mainFrame,
//    				"Expected " + getResourceMessage(eProducer));
//    		
//    	} catch (Exception ex) {
//    		JOptionPane.showMessageDialog(null, "Exception during estimation: " + ex);    
//    	} finally {
//    		if (eProducer != null)
//    			eProducer.dispose();
//    	}
//}
    
	private String getResourceMessage(Producer rProducer) {
		double moved = Math.round(rProducer.getTotalDistanceMoved() * 10.0) / 10.0;
		double extruded = Math.round(rProducer.getTotalDistanceExtruded() * 10.0) / 10.0;
		double extrudedVolume = Math.round(rProducer.getTotalVolumeExtruded() * 10.0) / 10.0;
		double time = Math.round(rProducer.getTotalElapsedTime() * 10.0) / 10.0;
		return "Total distance travelled=" + moved +
			"mm.  Total distance extruded=" + extruded +
			"mm.  Total volume extruded=" + extrudedVolume +
			"mm^3.  Elapsed time=" + time + "s";
	}
	
	public void dispose() 
	{
		Debug.d("Main dispose()");
		ftd.killThem();
		/// TODO This class should be fixed so it gets the dispose on window close
		try {
			// Attempt to save screen position if requested
			org.reprap.Preferences prefs = org.reprap.Preferences.getGlobalPreferences();
			if (prefs.loadBool("RememberWindowPosition")) {
				//prefs.setGlobalBool("MainWindowTop", xxx)
			}
		} catch (Exception ex) {
			
		}
		
		System.exit(0);
	}
	
	public static void main(String[] args) {
            
            Thread.currentThread().setName("Main");
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
            
            public void run() {
//                try {
//                     initComms();
//                }
//                catch (Exception ex) {
//                        JOptionPane.showMessageDialog(null, "Error initialising comms: " + ex);
//                                ex.printStackTrace();
//                }
                

                
                try {
                        Thread.currentThread().setName("RepRap");
                                gui = new Main();
                                gui.createAndShowGUI();
                }
                catch (Exception ex) {
                        JOptionPane.showMessageDialog(null, "Error in the main GUI: " + ex);
                                ex.printStackTrace();
                }
                
                gui.mainFrame.setFocusable(true);
                gui.mainFrame.requestFocus();
                BotConsoleFrame.main(null);

            }
        });

	}
        
        
        public static Main gui;
        
//        private static void initComms() throws Exception {
//
//            SNAPAddress myAddress = new SNAPAddress(localNodeNumber);
//
//            String port = "";
//            String err = "";
//            String machine = "simulator";
//			@SuppressWarnings("unused")
//			Boolean use_serial = false;
//
//			repRapAttached = false;
//			try
//			{
//	            port = org.reprap.Preferences.loadGlobalString("Port(name)");
//	            machine = org.reprap.Preferences.loadGlobalString("RepRap_Machine");
//				use_serial = org.reprap.Preferences.loadGlobalBool("GCodeUseSerial");
//			}
//			catch (Exception e)	{}
//
//			if (machine.equals("SNAPRepRap"))
//			{
//				try
//				{
//					communicator = new SNAPCommunicator(port, myAddress);
//				}
//				catch (gnu.io.NoSuchPortException e)
//				{
//					err = "\nCould not connect at " + port + ".\n\n";
//					err += "Check to make sure that is the right path.\n";
//					err += "Check that you have your serial connector plugged in.\n\n";
//					err += "The program will continue but your geometry preference has been set to 'nullcartesian' for this session.";
//
//					org.reprap.Preferences.setGlobalString("RepRap_Machine", "simulator");
//					
//					communicator = null;
//
//					throw new Exception(err);
//				}
//				catch (gnu.io.PortInUseException e)
//				{
//					err = "\nThe " + port + " port is already in use by another program, or your bot isn't plugged in.\n";
//					err += "The program will continue but your geometry preference has been set to 'nullcartesian' for this session.";
//
//					org.reprap.Preferences.setGlobalString("RepRap_Machine", "simulator");
//
//					throw new Exception(err);
//				}
//				catch (Exception e)
//				{
//					e.printStackTrace();
//				}
//				repRapAttached = true;
//			}
//		}
        
        public static void setRepRapPresent(boolean a)
        {
        	repRapAttached = a;
        }
        
        public static boolean repRapPresent()
        {
        	return repRapAttached;
        }

        
        public static Communicator getCommunicator() {
            return communicator;
        }

        private static final int localNodeNumber = 0;
    }
